"""
Compliance Template 核心业务逻辑
处理业务规则和数据转换，调用CRUD操作执行数据库交互
"""
from typing import Dict, Any, Optional
from uuid import UUID
from sqlalchemy.ext.asyncio import AsyncSession
from fastapi import HTTPException

from schemas.complianceTemplate import (
    ComplianceTemplateCreate,
    ComplianceTemplateUpdate,
    ComplianceTemplateResponse,
    ComplianceTemplateDetailResponse,
    ComplianceTemplatePagination,
    TemplateItemCreate,
    TemplateItemResponse
)
from crud import complianceTemplate as compliance_template_crud
from crud import assessmentPlan as assessment_plan_crud
from log import log_info, log_error

async def get_compliance_templates(
    db: AsyncSession,
    skip: int = 0,
    limit: int = 100,
    filters: Optional[Dict[str, Any]] = None
) -> ComplianceTemplatePagination:
    """
    获取合规模板列表，支持分页和过滤

    Args:
        db: 数据库会话
        skip: 跳过记录数
        limit: 返回记录限制
        filters: 过滤条件字典

    Returns:
        包含总记录数和合规模板列表的分页响应对象
    """
    templates, total = await compliance_template_crud.get_compliance_templates(db, skip, limit, filters)
    
    return ComplianceTemplatePagination(
        total=total,
        items=[ComplianceTemplateResponse.model_validate(template) for template in templates]
    )

async def get_compliance_template(
    db: AsyncSession,
    template_id: UUID,
    include_items: bool = False
) -> ComplianceTemplateResponse:
    """
    根据ID获取合规模板

    Args:
        db: 数据库会话
        template_id: 合规模板ID
        include_items: 是否包含模板项

    Returns:
        合规模板响应对象，未找到则返回None
    """
    db_template = await compliance_template_crud.get_compliance_template_by_id(db, template_id)
    if not db_template:
        log_info(f"Template not found with ID {template_id}", module="core.complianceTemplate")
        return None

    if include_items:
        # 获取关联的模板项
        template_items = await compliance_template_crud.get_template_items(db, template_id)
        
        # 构建详细响应
        response = ComplianceTemplateDetailResponse.model_validate(db_template)
        response.items = [TemplateItemResponse.model_validate(item) for item in template_items]
        return response
    
    # 返回基本响应
    return ComplianceTemplateResponse.model_validate(db_template)

async def create_compliance_template(
    db: AsyncSession,
    template_data: ComplianceTemplateCreate
) -> ComplianceTemplateResponse:
    """
    创建新的合规模板

    Args:
        db: 数据库会话
        template_data: 合规模板创建数据

    Returns:
        创建的合规模板响应对象
    """
    # 业务规则验证
    # 检查模板名称是否唯一
    existing_templates = await compliance_template_crud.get_compliance_templates(
        db, 
        filters={"name": template_data.name}
    )
    if existing_templates[1] > 0:
        log_error(f"Template name '{template_data.name}' already exists", module="core.complianceTemplate")
        raise HTTPException(status_code=400, detail=f"Template name '{template_data.name}' already exists")
    
    # 创建模板
    db_template = await compliance_template_crud.create_compliance_template(db, template_data)
    
    log_info(f"Successfully created compliance template with ID {db_template.id}", module="core.complianceTemplate")
    return ComplianceTemplateResponse.model_validate(db_template)

async def create_template_item(
    db: AsyncSession,
    item_data: TemplateItemCreate
) -> TemplateItemResponse:
    """
    创建新的模板项

    Args:
        db: 数据库会话
        item_data: 模板项创建数据

    Returns:
        创建的模板项响应对象
    """
    # 验证模板存在
    template_id = item_data.template_id
    db_template = await compliance_template_crud.get_compliance_template_by_id(db, template_id)
    if not db_template:
        log_error(f"Template not found with ID {template_id}", module="core.complianceTemplate")
        raise HTTPException(status_code=404, detail=f"Template not found with ID {template_id}")
    
    # 创建模板项
    db_item = await compliance_template_crud.create_template_item(db, item_data)
    
    log_info(f"Successfully created template item with ID {db_item.id}", module="core.complianceTemplate")
    return TemplateItemResponse.model_validate(db_item)

async def update_compliance_template(
    db: AsyncSession,
    template_id: UUID,
    template_data: ComplianceTemplateUpdate
) -> Optional[ComplianceTemplateResponse]:
    """
    更新合规模板

    Args:
        db: 数据库会话
        template_id: 合规模板ID
        template_data: 更新数据

    Returns:
        更新后的合规模板响应对象，未找到则返回None
    """
    # 检查模板是否存在
    db_template = await compliance_template_crud.get_compliance_template_by_id(db, template_id)
    if not db_template:
        log_info(f"Template not found with ID {template_id}", module="core.complianceTemplate")
        return None
    
    # 如果更新名称，检查是否与其他模板重名
    if template_data.name and template_data.name != db_template.name:
        existing_templates = await compliance_template_crud.get_compliance_templates(
            db, 
            filters={"name": template_data.name}
        )
        if existing_templates[1] > 0:
            log_error(f"Template name '{template_data.name}' already exists", module="core.complianceTemplate")
            raise HTTPException(status_code=400, detail=f"Template name '{template_data.name}' already exists")
    
    # 更新模板
    updated_template = await compliance_template_crud.update_compliance_template(db, template_id, template_data)
    if not updated_template:
        log_error(f"Failed to update template with ID {template_id}", module="core.complianceTemplate")
        return None
    
    log_info(f"Successfully updated compliance template with ID {template_id}", module="core.complianceTemplate")
    return ComplianceTemplateResponse.model_validate(updated_template)

async def delete_compliance_template(db: AsyncSession, template_id: UUID) -> bool:
    """
    删除合规模板

    Args:
        db: 数据库会话
        template_id: 合规模板ID

    Returns:
        删除成功返回True，未找到则返回False
    """
    # 检查模板是否存在
    db_template = await compliance_template_crud.get_compliance_template_by_id(db, template_id)
    if not db_template:
        log_info(f"Template not found with ID {template_id}", module="core.complianceTemplate")
        return False
    
    # 删除模板
    result = await compliance_template_crud.delete_compliance_template(db, template_id)
    
    if result:
        log_info(f"Successfully deleted compliance template with ID {template_id}", module="core.complianceTemplate")
    else:
        log_error(f"Failed to delete template with ID {template_id}", module="core.complianceTemplate")
    
    return result

async def get_template_item(db: AsyncSession, item_id: UUID) -> TemplateItemResponse:
    """
    根据ID获取单个模板项

    Args:
        db: 数据库会话
        item_id: 模板项ID

    Returns:
        模板项响应对象
        
    Raises:
        HTTPException: 当模板项不存在时
    """
    try:
        item = await compliance_template_crud.get_template_item_by_id(db, item_id)
        if not item:
            raise HTTPException(
                status_code=404,
                detail=f"Template item with ID {item_id} not found"
            )
        log_info(f"Successfully retrieved template item with ID {item_id}")
        return TemplateItemResponse.model_validate(item)
    except HTTPException:
        raise
    except Exception as e:
        log_error(f"Error retrieving template item with ID {item_id}: {str(e)}")
        raise HTTPException(
            status_code=500,
            detail=f"Error retrieving template item: {str(e)}"
        )

async def delete_template_item(db: AsyncSession, item_id: UUID) -> bool:
    """
    删除模板项

    Args:
        db: 数据库会话
        item_id: 模板项ID

    Returns:
        删除成功返回True，未找到则返回False
    """
    try:
        deleted = await compliance_template_crud.delete_template_item(db, item_id)
        if deleted:
            log_info(f"Successfully deleted template item with ID {item_id}")
        else:
            log_info(f"Failed to delete template item with ID {item_id}: Not found")
        return deleted
    except Exception as e:
        log_error(f"Error deleting template item with ID {item_id}: {str(e)}")
        raise HTTPException(
            status_code=500,
            detail=f"Error deleting template item: {str(e)}"
        )

async def get_template_items_by_assessment_plan(
    db: AsyncSession,
    assessment_plan_id: UUID,
    filters: Optional[Dict[str, Any]] = None
) -> list[TemplateItemResponse]:
    """
    根据评估计划ID和多种过滤条件获取对应模板的模板项列表
    用于数据安全评估（105）等场景，根据评估计划查询其使用的模板项
    
    Args:
        db: 数据库会话
        assessment_plan_id: 评估计划ID
        filters: 过滤条件字典，支持以下字段：
            - title: 标题过滤（支持模糊匹配）
            - compliance_type: 合规类型过滤（risk/guarantee）
            - maturity_level: 成熟度等级过滤
            - description: 描述过滤（支持模糊匹配）
            - guide: 指导说明过滤（支持模糊匹配）
    
    Returns:
        模板项响应对象列表
        
    Raises:
        HTTPException: 当评估计划不存在或未关联模板时
    """
    try:
        # 1. 根据 assessment_plan_id 查询评估计划
        assessment_plan = await assessment_plan_crud.get_assessment_plan_by_id(db, assessment_plan_id)
        if not assessment_plan:
            log_error(f"未找到评估计划，ID: {assessment_plan_id}", module="core.complianceTemplate")
            raise HTTPException(
                status_code=404,
                detail=f"未找到评估计划，ID: {assessment_plan_id}"
            )
        
        # 2. 检查评估计划是否关联了模板
        if not assessment_plan.template_id:
            log_error(f"评估计划未关联模板，评估计划ID: {assessment_plan_id}", module="core.complianceTemplate")
            raise HTTPException(
                status_code=400,
                detail=f"评估计划未关联模板，评估计划ID: {assessment_plan_id}"
            )
        
        # 3. 根据 template_id 和 filters 查询模板项
        template_items = await compliance_template_crud.get_template_items_by_filters(
            db, 
            assessment_plan.template_id, 
            filters
        )
        
        log_info(f"成功查询到 {len(template_items)} 个模板项，评估计划ID: {assessment_plan_id}", 
                module="core.complianceTemplate")
        
        # 4. 转换为响应对象
        return [TemplateItemResponse.model_validate(item) for item in template_items]
        
    except HTTPException:
        raise
    except Exception as e:
        log_error(f"查询评估计划模板项失败，评估计划ID: {assessment_plan_id}，错误: {str(e)}", 
                 module="core.complianceTemplate")
        raise HTTPException(
            status_code=500,
            detail=f"查询模板项失败: {str(e)}"
        )
